<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>06_迭代对象-可迭代对象场景</title>
  <!-- 
  在 JavaScript 中，可迭代对象的场景非常广泛，它们在处理数据集合时提供了极大的便利。
  1. 遍历数据集合：
    - 可迭代对象允许使用  `for...of`  循环来遍历集合中的每个元素。这使得代码更加简洁和可读。
  const array = [1, 2, 3];
    for (const value of array) {
        console.log(value); // 输出 1, 2, 3
    }
  2. 使用展开运算符：
    - 可迭代对象可以与展开运算符（ `...` ）结合使用，方便地将其内容展开为数组或其他结构。
  const set = new Set([1, 2, 3]);
    const array = [...set]; // [1, 2, 3]
  3. 数组转换：
    - 使用  `Array.from()`  方法可以将类数组对象或可迭代对象转换为数组。
  const str = "hello";
    const charArray = Array.from(str); // ['h', 'e', 'l', 'l', 'o']
  4. 实现自定义可迭代对象：
    - 开发者可以通过实现  `Symbol.iterator`  方法来创建自定义的可迭代对象。这为特定的数据结构提供了灵活的迭代方式。
  class MyCollection {
        constructor() {
            this.items = [];
        }
        add(item) {
            this.items.push(item);
        }
        [Symbol.iterator]() {
            let index = 0;
            const items = this.items;
            return {
                next() {
                    if (index < items.length) {
                        return { value: items[index++], done: false };
                    }
                    return { done: true };
                }
            };
        }
    }

    const collection = new MyCollection();
    collection.add(1);
    collection.add(2);
    for (const item of collection) {
        console.log(item); // 输出 1, 2
    }
  5. 与高阶函数结合使用：
    - 可迭代对象可以与高阶函数（如  `map` ,  `filter` ,  `reduce` ）结合使用，使得数据处理更加灵活。
  const array = [1, 2, 3];
    const doubled = array.map(x => x * 2); // [2, 4, 6]
  6. 异步迭代：
    - 使用  `for await...of`  循环可以遍历异步可迭代对象（如异步生成器），这在处理异步操作时非常有用。
  async function* asyncGenerator() {
        yield 1;
        yield 2;
        yield 3;
    }

    (async () => {
        for await (const value of asyncGenerator()) {
            console.log(value); // 输出 1, 2, 3
        }
    })();
  7. 结合 DOM 操作：
    - 在浏览器环境中， `NodeList`  和  `HTMLCollection`  等可迭代对象常用于 DOM 操作，使得在处理多个元素时更加方便。
  const divs = document.querySelectorAll('div');
    for (const div of divs) {
        console.log(div); // 输出每个 div 元素
    }
  -->
</head>
<body>

  <script>
    // 1. 用在特定的语法上
    const arr = [1, 2, 3, 4, 5];
    const info = {
      name: "iterator-name",
      age: 18,
      gender: "male",
      [Symbol.iterator]() {
        const values = Object.values(this)
        return {
          next() {
            this.index = this.index || 0;
            if (this.index === values.length) {
              return {
                done: true
              }
            }
            return {
              value: values[this.index++],
              done: false
            }
          }
        }
      }
    }
    
    function foo(arg1, arg2, arg3) {
      console.log(arg1, arg2, arg3);
    }

    foo(...info)

    // 2.一些类的构造方法中, 也是传入的可迭代对象
    const set = new Set(["a", "b", "c", "d"])
    const infoSet = new Set(info)
    console.log(set, infoSet);

    // 3. 一些常用的方法
    const p1 = Promise.resolve("resolve-p1")
    const p2 = Promise.resolve("resolve-p2")
    const p3 = Promise.resolve("resolve-p3")
    const pSet = new Set([p1, p2, p3])
    Promise.all(pSet).then(res => {
      console.log("Promise.all :", res);
    })

    function bar() {
      console.log("bar-arguments", arguments);
      // 将arguments转换为数组
      const arr = Array.from(arguments)
      console.log(arr);
    }
    bar(1, 2, 3, 4, 5)

  </script>
  
</body>
</html>

